package com.caigou.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.caigou.bean.cms.entity.*;
import com.caigou.bean.cms.param.*;
import com.caigou.bean.exam.entity.UserInfo;
import com.caigou.bean.exam.entity.Users;
import com.caigou.component.OSSComponent;
import com.caigou.component.RedisComponent;
import com.caigou.component.RedisObjectComponent;
import com.caigou.component.SnowflakeComponent;
import com.caigou.constant.NewsConstant;
import com.caigou.mapper.cms.*;
import com.caigou.mapper.exam.UserInfoMapper;
import com.caigou.mapper.exam.UsersMapper;
import com.caigou.service.LessonService;
import com.caigou.util.Result;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service("lessonService")
public class LessonServiceImpl implements LessonService {
    @Resource
    private LessonMapper lessonMapper;
    @Resource
    private LessonAttachmentMapper lessonAttachmentMapper;
    @Resource
    private LessonObjectMapper lessonObjectMapper;
    @Resource
    private LessonSpanMapper lessonSpanMapper;
    @Resource
    private UsersMapper usersMapper;
    @Resource
    private UserInfoMapper userInfoMapper;
    @Resource
    private UserBaseInfoMapper userBaseInfoMapper;
    @Resource
    private AttachmentConfigMapper attachmentConfigMapper;

    @Resource
    private SnowflakeComponent snowflakeComponent;// 雪花UUID组件
    @Resource
    private OSSComponent ossComponent;

    @Resource
    private RedisComponent redisComponent;
    @Resource
    private RedisObjectComponent redisObjectComponent;


    public Lesson selectByPrimaryKey(int id) {
        return lessonMapper.selectByPrimaryKey(id);
    }

    public int insertSelective(Lesson lesson) {
        return lessonMapper.insertSelective(lesson);
    }

    public Result saveLesson(Lesson lesson, MultipartFile[] files, MultipartFile image) {
        AttachmentConfig attachmentConfig = attachmentConfigMapper.selectByType(2);//我要讲课的配置
        if(attachmentConfig!=null) {
            int maxCount = attachmentConfig.getMaxCount();
            if (files.length > maxCount) {
                return Result.error("最多只能上传" + maxCount + "个附件", "最多只能上传" + maxCount + "个附件");
            }
            int maxSize = attachmentConfig.getMaxSize();
            for(MultipartFile multipartFile:files){
                if(multipartFile.getSize()>maxSize*1024*1024){
                    return Result.error("文件最大" + maxSize + "MB，请重新上传", "文件最大" + maxSize + "MB，请重新上传");
                }
            }
        }

        //首先处理上传头像
        String imageUrl = this.uploadImage(image);
        //其次保存Lesson对象
        lesson.setImageUrl(imageUrl);
        Date currentTime = new Date(System.currentTimeMillis());
        lesson.setCreateTime(currentTime);
        lesson.setUpdateTime(currentTime);
        int result = lessonMapper.insertSelective(lesson);
        //最后处理讲课课件
        if(result>0){
            //多文件上传
            int failCount = 0;//文件上传失败数量
            int successCount = 0;//文件上传成功数量
            LessonService proxy = (LessonService) AopContext.currentProxy();
            StringBuffer sb = new StringBuffer("第");
            int uploadResult = 0;
            for (int i = 0; i < files.length; i++) {
                MultipartFile multipartFile = files[i];
                log.info("before 上传讲课file={}, i={}", multipartFile.getOriginalFilename(), i);
                try {
                    uploadResult = proxy.uploadLesson(multipartFile, i, lesson.getId());
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                }
                if (uploadResult > 0) {
                    successCount++;
                } else {
                    failCount++;
                    sb.append((i + 1)).append("、");
                }
            }
            if(failCount==0){//全部成功
                return Result.success("讲课课件成功");
            }else if(successCount==0){//全部失败
                return Result.error(failCount+"个讲课课件上传全部失败", failCount+"个讲课课件传全部失败");
            }else{//部分成功、部分失败
                sb.deleteCharAt(sb.length() - 1);//删除最后一个字符
                return Result.custom(400,failCount+"个（"+sb.toString()+")讲课课件上传失败,"+successCount+"个讲课课件上传成功",failCount+"个（"+sb.toString()+")讲课课件上传失败,"+successCount+"个讲课课件上传成功");
            }

        }else{
            return Result.error("上传讲课课件失败", "上传讲课课件失败");
        }
    }

    private String uploadImage(MultipartFile image) {
        if(image==null){
            return null;
        }
        String fileUrl = null;
        try {
            String fileName = image.getOriginalFilename();
            String fileExtension = "";
            int idx = fileName.lastIndexOf(".");
            if (idx > 0) {
                fileExtension = fileName.substring(idx);
            } else {
                log.error("上传图片错误，没有扩展名, fileName={}", fileName);
                return null;
            }
            //文件重命名
            long snowflakeId = snowflakeComponent.getInstance().nextId();
            String newFileName = snowflakeId + fileExtension;
            String strSnowflakeId = String.valueOf(snowflakeId);
            int length = strSnowflakeId.length();
            String contributeFolder = NewsConstant.LESSON_ROOT + "/" + strSnowflakeId.substring(length - 4, length - 2) + "/" + strSnowflakeId.substring(length - 2, length) + "/";
            //上传图片
            InputStream originInputStream = image.getInputStream();
            fileUrl = ossComponent.uploadToOSS(originInputStream, fileName, newFileName, contributeFolder);
        } catch (IOException ioe) {
            log.error(ioe.getMessage(), ioe);
        }
        return fileUrl;
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Throwable.class)
    public int uploadLesson(MultipartFile multipartFile, int i, int lessonId) {
        try {
            String fileName = multipartFile.getOriginalFilename();
            log.info("第{}个文稿，fileName={}", i, fileName);
            String fileExtension = "";
            int idx = fileName.lastIndexOf(".");
            if (idx > 0) {
                fileExtension = fileName.substring(idx);
            } else {
                log.error("上传文稿错误，没有扩展名, fileName={}", fileName);
                return 0;
            }
            //文件重命名
            long snowflakeId = snowflakeComponent.getInstance().nextId();
            String newFileName = snowflakeId + fileExtension;
            String strSnowflakeId = String.valueOf(snowflakeId);
            int length = strSnowflakeId.length();
            String contributeFolder = NewsConstant.LESSON_ROOT + "/" + strSnowflakeId.substring(length - 4, length - 2) + "/" + strSnowflakeId.substring(length - 2, length) + "/";

            //上传讲课文件
            InputStream originInputStream = multipartFile.getInputStream();
            String fileUrl = ossComponent.uploadToOSS(originInputStream, fileName, newFileName, contributeFolder);

            LessonAttachment lessonAttachment = new LessonAttachment();
            lessonAttachment.setLessonId(lessonId);
            lessonAttachment.setFileName(multipartFile.getOriginalFilename());
            lessonAttachment.setFileSize(multipartFile.getSize());
            lessonAttachment.setFileType(fileExtension);
            lessonAttachment.setFileUrl(fileUrl);
            Date currentTime = new Date(System.currentTimeMillis());
            lessonAttachment.setCreateTime(currentTime);
            lessonAttachment.setUpdateTime(currentTime);
            return lessonAttachmentMapper.insertSelective(lessonAttachment);
        } catch (IOException ioe) {
            log.error(ioe.getMessage(), ioe);
            throw new RuntimeException(ioe);
        }
    }

    public LessonObject selectLessonObjectByPrimaryKey(int id){
        return lessonObjectMapper.selectByPrimaryKey(id);
    }

    public int saveLessonObject(LessonObject lessonObject){
        return lessonObjectMapper.insertSelective(lessonObject);
    }

    public Result saveLessonObject(LessonObjectParam param){
        int count = lessonObjectMapper.getLessonObjectCount();
        if(count>=15){
            return Result.error("授课对象名称已经超过15个，不能再增加", "授课对象名称已经超过15个，不能再增加");
        }
        LessonObject lessonObject = new LessonObject();
        BeanUtil.copyProperties(param, lessonObject);
        Date currentTime = new Date(System.currentTimeMillis());
        lessonObject.setCreateTime(currentTime);
        lessonObject.setUpdateTime(currentTime);
        int result = 0;
        try{
            result = this.saveLessonObject(lessonObject);
        }catch(DataAccessException e){
            log.error(e.getMessage(), e);
            return Result.error("授课对象名称不能重复", "授课对象名称不能重复");
        }
        if(result>0){
            return Result.success("新增授课对象名称成功");
        }else{
            return Result.error("新增授课对象名称失败", "新增授课对象名称失败");
        }
    }

    public int updateLessonObject(LessonObject lessonObject){
        lessonObject.setUpdateTime(new Date(System.currentTimeMillis()));
        return lessonObjectMapper.updateLessonObject(lessonObject);
    }

    public Result updateLessonObject(LessonObjectParam param){
        LessonObject lessonObject = new LessonObject();
        BeanUtil.copyProperties(param, lessonObject);
        int result = this.updateLessonObject(lessonObject);
        if(result>0){
            return Result.success("更新授课对象名称成功");
        }else{
            return Result.error("更新授课对象名称失败", "更新授课对象名称失败");
        }
    }

    public Result deleteLessonObject(Integer id){
//        int count = lessonMapper.getCountByLessonObjectId(id);
//        if(count>0){
//            return Result.error("政府采购从业时间名称已经使用，不能删除", "政府采购从业时间名称已经使用，不能删除");
//        }
        int result = lessonObjectMapper.deleteLessonObject(id);
        if(result>0){
            return Result.success("删除授课对象名称成功");
        }else{
            return Result.error("删除授课对象名称失败", "删除授课对象名称失败");
        }
    }

    public List<LessonObject> listLessonObject(){
        return lessonObjectMapper.listLessonObject();
    }

    public LessonSpan selectLessonSpanByPrimaryKey(int id){
        return lessonSpanMapper.selectByPrimaryKey(id);
    }

    public int saveLessonSpan(LessonSpan lessonSpan){
        return lessonSpanMapper.insertSelective(lessonSpan);
    }

    public Result saveLessonSpan(LessonSpanParam param){
        int count = lessonSpanMapper.getLessonSpanCount();
        if(count>=8){
            return Result.error("政府采购从业时间名称已经超过8个，不能再增加", "政府采购从业时间名称已经超过8个，不能再增加");
        }
        LessonSpan lessonSpan = new LessonSpan();
        BeanUtil.copyProperties(param, lessonSpan);
        Date currentTime = new Date(System.currentTimeMillis());
        lessonSpan.setCreateTime(currentTime);
        lessonSpan.setUpdateTime(currentTime);
        int result = 0;
        try{
            result = this.saveLessonSpan(lessonSpan);
        }catch(DataAccessException e){
            log.error(e.getMessage(), e);
            return Result.error("政府采购从业时间名称不能重复", "政府采购从业时间名称不能重复");
        }
        if(result>0){
            return Result.success("新增政府采购从业时间名称");
        }else{
            return Result.error("新增政府采购从业时间名称失败", "新增政府采购从业时间名称失败");
        }
    }

    public int updateLessonSpan(LessonSpan lessonSpan){
        lessonSpan.setUpdateTime(new Date(System.currentTimeMillis()));
        return lessonSpanMapper.updateLessonSpan(lessonSpan);
    }

    public Result updateLessonSpan(LessonSpanParam param){
        LessonSpan lessonSpan = new LessonSpan();
        BeanUtil.copyProperties(param, lessonSpan);
        int result = this.updateLessonSpan(lessonSpan);
        if(result>0){
            return Result.success("更新政府采购从业时间名称成功");
        }else{
            return Result.error("更新政府采购从业时间名称失败", "更新政府采购从业时间名称失败");
        }
    }

    public Result deleteLessonSpan(Integer id){
        int count = lessonMapper.getCountBySpanId(id);
        if(count>0){
            return Result.error("政府采购从业时间名称已经使用，不能删除", "政府采购从业时间名称已经使用，不能删除");
        }
        int result = lessonSpanMapper.deleteLessonSpan(id);
        if(result>0){
            return Result.success("删除政府采购从业时间名称成功");
        }else{
            return Result.error("删除政府采购从业时间名称失败", "删除政府采购从业时间名称失败");
        }
    }

    public List<LessonSpan> listLessonSpan(){
        return lessonSpanMapper.listLessonSpan();
    }

    public Result getLessonConfig(){
//        String lessonNotice = redisComponent.get(NewsConstant.LESSON_NOTICE_KEY);
//        Integer maxCount = (Integer)redisObjectComponent.get(NewsConstant.LESSON_ATTACHMENT_MAX_COUNT_KEY);
//        Integer maxSize = (Integer)redisObjectComponent.get(NewsConstant.LESSON_ATTACHMENT_MAX_SIZE_KEY);
//        String attachmentNote = redisComponent.get(NewsConstant.LESSON_ATTACHMENT_NOTE_KEY);
//        LessonConfigParam param = new LessonConfigParam();
//        param.setLessonNotice(lessonNotice);
//        param.setLessonMaxCount(maxCount);
//        param.setAttachmentMaxSize(maxSize);
//        param.setAttachmentNote(attachmentNote);
//        return Result.success(param);
        AttachmentConfig attachmentConfig = attachmentConfigMapper.selectByType(2);
        return Result.success(attachmentConfig);

    }

    public Result saveLessonConfig(AttachmentConfigParam param){
//        boolean f1 = redisComponent.set(NewsConstant.LESSON_NOTICE_KEY, param.getLessonNotice());
//        boolean f2 = redisObjectComponent.set(NewsConstant.LESSON_ATTACHMENT_MAX_COUNT_KEY, param.getLessonMaxCount());
//        boolean f3 = redisObjectComponent.set(NewsConstant.LESSON_ATTACHMENT_MAX_SIZE_KEY, param.getAttachmentMaxSize());
//        boolean f4 = redisComponent.set(NewsConstant.LESSON_ATTACHMENT_NOTE_KEY, param.getAttachmentNote());
//        if(f1&&f2&&f3&&f4){
//            return Result.success("保存讲课配置成功");
//        }else{
//            return Result.error("保存讲课配置失败", "保存讲课配置失败");
//        }
        AttachmentConfig attachmentConfig = new AttachmentConfig();
        BeanUtil.copyProperties(param, attachmentConfig);
        attachmentConfig.setUpdateTime(new Date(System.currentTimeMillis()));
        int result = attachmentConfigMapper.updateByPrimaryKeySelective(attachmentConfig);
        if(result>0){
            return Result.success("保存讲课配置成功");
        }else{
            return Result.error("保存讲课配置失败", "保存讲课配置失败");
        }
    }

    public Result queryLesson(LessonQueryParam param){
        //先判断并查询Users表，因为users、user_inf表是在exam库
        List<String> userIdList = null;
        Set<String> hashSet = null;
        if(param.getLessonUser()!=null && param.getLessonUser().trim().length()>0){
            Users users = usersMapper.findUserByTel(param.getLessonUser());
            List<UserInfo> userInfoList = userInfoMapper.findUserInfoByNicknamePrecisMatch(param.getLessonUser());
            if(users!=null||(userInfoList!=null&&userInfoList.size()>0)){
                hashSet = new HashSet<String>();
                if(users!=null){
                    hashSet.add(users.getUserid());
                }
                if(userInfoList!=null && userInfoList.size()>0){
                    for(UserInfo userInfo:userInfoList){
                        hashSet.add(userInfo.getUserid());
                    }
                }
            }
            if(hashSet==null){
                List<Lesson> lessonList = new ArrayList<Lesson>();
                PageInfo<Lesson> lessonPageInfo = new PageInfo<Lesson>(lessonList);
                return Result.success(lessonPageInfo);
            }

        }
        if(hashSet!=null && !hashSet.isEmpty()){
            userIdList = new ArrayList<String>(hashSet);
            param.setUserIdList(userIdList);
        }
        Page<?> page = null;
        if(param.getPageNum()!=null && param.getPageSize() !=null){
            page = PageHelper.startPage(param.getPageNum(), param.getPageSize());
        }
        List<Lesson> lessonList = lessonMapper.queryLesson(param);
        //转化每一个lessonObject为lessonObjectName
        List<LessonObject> lessonObjectList = lessonObjectMapper.listLessonObject();
        Map<Integer, String> lessonObjectMap = lessonObjectList.stream().collect(Collectors.toMap(LessonObject::getId, LessonObject::getObjectName));
        for(Lesson lesson:lessonList){
            String lessonObjects = lesson.getLessonObjects();
            String[] array = lessonObjects.split(",");
            StringBuffer sb = new StringBuffer();
            for(String lessonObjectId:array){
                Integer objId = Integer.parseInt(lessonObjectId);
                String lessonObjectName = lessonObjectMap.get(objId);
                sb.append(lessonObjectName).append(",");
            }
            int length = sb.length();
            if(length>0){
                lesson.setLessonObjectNames(sb.toString().substring(0, length-1));
            }
        }
        PageInfo<Lesson> lessonPageInfo = new PageInfo<Lesson>(lessonList);
        return Result.success(lessonPageInfo);
    }

    public Result getLessonDetail(LessonParam param){
        Lesson lesson = this.selectByPrimaryKey(param.getId());

        //转化lessonObject为lessonObjectName
        List<LessonObject> lessonObjectList = lessonObjectMapper.listLessonObject();
        Map<Integer, String> lessonObjectMap = lessonObjectList.stream().collect(Collectors.toMap(LessonObject::getId, LessonObject::getObjectName));
        String lessonObjects = lesson.getLessonObjects();
        String[] array = lessonObjects.split(",");
        StringBuffer sb = new StringBuffer();
        for(String lessonObjectId:array){
            Integer objId = Integer.parseInt(lessonObjectId);
            String lessonObjectName = lessonObjectMap.get(objId);
            sb.append(lessonObjectName).append(",");
        }
        int length = sb.length();
        if(length>0){
            lesson.setLessonObjectNames(sb.toString().substring(0, length-1));
        }

        String userId = lesson.getUserId();
        String processUserId = lesson.getProcessUserId();
        Users user = usersMapper.queryUserDetail(userId);//usersMapper.findUserByUserId(userId);
        UserBaseInfo userBaseInfo = userBaseInfoMapper.findUserBaseInfoByUserId(processUserId);
        List<LessonAttachment> list = lessonAttachmentMapper.listByLessonId(param.getId());
        lesson.setUser(user);
        lesson.setUserBaseInfo(userBaseInfo);
        lesson.setLessonAttachmentList(list);

        return Result.success(lesson);
    }

    public Result processLesson(LessonParam param, String processUserId){
        Lesson lesson = new Lesson();
        BeanUtil.copyProperties(param, lesson);
        lesson.setProcessUserId(processUserId);
        lesson.setProcessTime(new Date(System.currentTimeMillis()));
        int result = lessonMapper.updateLesson(lesson);
        if(result>0){
            return Result.success("处理我要讲课课件成功");
        }else{
            return Result.error("处理我要讲课课件失败", "处理我要讲课课件失败");
        }
    }

    public int getCountByProcessStatus(int processStatus){
        int count = lessonMapper.getCountByProcessStatus(processStatus);
        return count;
    }
}
